package com.gismore.demo.security;

import com.gismore.demo.common.constants.FConst;
import com.gismore.demo.common.service.LocaleMessageSourceService;
import com.gismore.demo.config.AppConfig;
import com.gismore.demo.db.domain.SecUser;
import com.gismore.demo.db.service.ISecUserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created by lei on 2017/5/26.
 */
public class StatelessAuthcFilter extends AccessControlFilter {

	@Autowired
	private ISecUserService secUserService;

	@Autowired
	private LocaleMessageSourceService localeMessageSourceService;

	@Override
	protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object mappedValue) throws Exception {
		HttpServletRequest request = (HttpServletRequest) servletRequest;
		String uri = request.getRequestURI();

		Set<String> shiroAnonUrls = AppConfig.me().shiroAnonUrls();
		return shiroAnonUrls.contains(uri);
	}

	@Override
	protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
		HttpServletRequest request = (HttpServletRequest) servletRequest;
		//1、接收客户端通过Header传递的JWT Token
		String accessToken = request.getHeader(FConst.PARAMS_ACCESS_TOKEN);
		//2、验证JWT Token是否有效
		SecUser secUser = secUserService.findByToken(accessToken);
		if(secUser != null){
			//3、客户端请求的参数列表
			Map<String, String[]> params = new HashMap<String, String[]>(request.getParameterMap());
			//4、生成无状态的Token
			StatelessToken token = new StatelessToken(secUser.getUsername(),secUser.getPassword(), params);

			try {
				//5、委托给Realm登录
				Subject subject = getSubject(servletRequest,servletResponse);
				subject.login(token);
				subject.checkPermission(request.getRequestURI()+":"+request.getMethod().toLowerCase());
				return true;
			} catch (AuthenticationException e) {
				e.printStackTrace();
				//6、登录失败
				onLoginFail(servletResponse);
				return false;
			}
		}else{
			onLoginFail(servletResponse);
			return false;
		}
	}

	//登录失败时默认返回403状态码
	private void onLoginFail(ServletResponse response) throws IOException {
		HttpServletResponse httpResponse = (HttpServletResponse) response;
		httpResponse.setStatus(HttpServletResponse.SC_OK);
		httpResponse.setContentType("application/json;charset=UTF-8");
		httpResponse.getWriter().write(localeMessageSourceService.getMessage(403).toString());
	}
}
